import { Menu } from "@prisma/client";
import { MenuResponseDTO } from "../dtos/menu.dto";
import { getTwoWeeksDates } from "../utils/date.util";
import prisma from "../config/database";
import { format } from "date-fns";

export class MenuService {
  /**
   * 创建或更新菜单及关联菜品
   */
  public static async upsertMenu(
    date: string,
    dishIds: number[]
  ): Promise<Menu> {
    return prisma.$transaction(async (tx) => {
      // 创建/更新菜单
      const menu = await tx.menu.upsert({
        where: { date: new Date(date) },
        update: {},
        create: { date: new Date(date) },
      });

      // 删除旧关联
      await tx.menuDishes.deleteMany({
        where: { menuId: menu.id },
      });

      // 验证菜品存在
      const existingDishes = await tx.dishes.findMany({
        where: { id: { in: dishIds } },
      });

      if (existingDishes.length !== dishIds.length) {
        throw new Error("部分菜品不存在");
      }

      // 创建新关联
      await tx.menuDishes.createMany({
        data: dishIds.map((dishId, index) => ({
          menuId: menu.id,
          dishesId: dishId,
          order: index + 1,
        })),
      });

      return menu;
    });
  }

  // 根据日期获取菜单及关联菜品
  public static async getMenuByDate(
    date: string,
    userId = 0
  ): Promise<MenuResponseDTO> {
    // 查询菜单
    const dailyMenu = await prisma.menu.findUnique({
      where: { date: new Date(date) },
    });

    // 菜单不存在时创建，返回的菜品为空数组
    if (!dailyMenu) {
      const newMenu = await prisma.menu.create({
        data: { date: new Date(date) },
      });
      return {
        ...newMenu,
        dishes: [],
      };
    }

    // 菜单存在，则返回的菜品需要包含是否被评分的字段
    const existingMenu = await prisma.menu.findUnique({
      where: { id: dailyMenu.id },
      include: {
        menuDishes: {
          include: {
            dishes: {
              include: {
                category: {
                  select: {
                    name: true,
                  },
                },
                // 用户id关联评分记录
                ratings: {
                  where: {
                    userId,
                    menuId: dailyMenu.id,
                  },
                  select: {
                    score: true,
                  },
                },
              },
            },
          },
          orderBy: { order: "asc" },
        },
      },
    });

    // 菜单存在时，转换为 MenuResponseDTO 格式
    const dishes = existingMenu!.menuDishes.map((item) => {
      const { order, dishes } = item;
      const { category, ratings, ...rest } = dishes;
      return {
        ...rest,
        order,
        categoryName: category.name,
        description: rest.description || "",
        picture: rest.picture || "",
        thumbnail: rest.thumbnail || "",
        isScored: ratings.length > 0,
      };
    });

    const { menuDishes, ...menu } = existingMenu!;

    return {
      ...menu,
      dishes,
    };
  }

  // 查询本周和下周菜单
  static async getWeeksMenuDishes() {
    // 生成本周+下周共14天的日期范围
    const daysRange = getTwoWeeksDates().map((d) => new Date(d));

    const menus = await prisma.menu.findMany({
      where: { date: { in: daysRange } },
      include: {
        menuDishes: {
          include: {
            dishes: {
              select: { name: true },
            },
          },
        },
      },
    });

    // 补全没有设置的菜单
    const menuList = daysRange.map((day) => {
      const date = day.getTime();
      const menu = menus.find((m) => m.date.getTime() === date);
      // 没有设置菜单的日期，菜品返回空数组
      if (!menu) {
        return {
          date: format(day, "yyyy-MM-dd"),
          dishes: [],
        };
      }

      return {
        date: format(menu.date, "yyyy-MM-dd"),
        dishes: menu.menuDishes.map((md) => md.dishes.name),
      };
    });

    return menuList;
  }
}
